package top.hidoctor.auscultation.feature.activity;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Intent;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.ParcelUuid;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import com.chad.library.adapter.base.BaseQuickAdapter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.UUID;

import top.hidoctor.auscultation.R;
import top.hidoctor.auscultation.adapter.DevicesAdapter;
import top.hidoctor.auscultation.base.BaseActivity;
import top.hidoctor.auscultation.bean.MyBluetoothDevice;
import top.hidoctor.auscultation.utils.HexUtil;

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public class BluetoothActivity2 extends BaseActivity implements View.OnClickListener {
    private Button btn_scan;
    private HashSet<Object> bluetoothDeviceSet;
    private BluetoothAdapter bluetoothAdapter;
    //  如果蓝牙没有开启
    private final static int REQUEST_ENABLE = 100;
    private RecyclerView recycler;
    private List<MyBluetoothDevice> list = new ArrayList<>();
    private DevicesAdapter adapter;
    //  用户发送指令的操作
    private BluetoothGattCharacteristic writeBluetoothGattCharacteristic;

    //  用于开启通知的操作
    private BluetoothGattCharacteristic notificationBluetoothGattCharacteristic;


    //  服务和特征值
    private UUID write_UUID_service;
    private UUID write_UUID_chara;

    private UUID read_UUID_service;
    private UUID read_UUID_chara;

    private UUID notify_UUID_service;
    private UUID notify_UUID_chara;

    private UUID indicate_UUID_service;
    private UUID indicate_UUID_chara;
    private int pos;
    private MyBluetoothDevice device;
    private BluetoothGatt bluetoothGatt;
    private boolean isConnect = false;
    private Handler handler;
    private AudioTrack tracker;
    private boolean isRecord = false;

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.act_bluetooth2);
        initView();
        initEvent();
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void initEvent() {
        // 初始化数据
        bufferQueue = new LinkedList<>();
        int bufferSize = AudioTrack.getMinBufferSize(frequency, channelOutConfig, audioEncoding);
        tracker = new AudioTrack(AudioManager.STREAM_RING, frequency, channelOutConfig, audioEncoding, bufferSize, AudioTrack.MODE_STREAM);

        log("初始化蓝牙扫描 的 set 集合");
        bluetoothDeviceSet = new HashSet<>();

        log("开始获取蓝牙适配器");
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        if (bluetoothAdapter != null) {

            log("bluetoothAdapter 不为 null 当前设备支持蓝牙");

            if (!bluetoothAdapter.isEnabled()) {
                log("蓝牙未启动,正在使用 intent 启用蓝牙");
                Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(intent, REQUEST_ENABLE);
            } else {
                log("蓝牙已经启动，不需要使用 intent 启动蓝牙");

//                String[] uuids = new String[1];
//                uuids[0] = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E";
                List<ScanFilter> flilters = new ArrayList<>();
                ScanFilter.Builder builder = new ScanFilter.Builder();
                builder.setServiceUuid(new ParcelUuid(UUID.fromString("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")));
                flilters.add(builder.build());
                ScanSettings.Builder builder2 = new ScanSettings.Builder();
                bluetoothAdapter.getBluetoothLeScanner().startScan(flilters, builder2.build(), scanCallback);
                log("开始扫描蓝牙设备");
            }

        } else {
            log("bluetoothAdapter 为 null 所以当前设备不支持蓝牙");
        }
    }

    //  蓝牙开始扫描回调
    private ScanCallback scanCallback = new ScanCallback() {
        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);

            //  bluetoothDevice 为扫描到的蓝牙设备
            BluetoothDevice bluetoothDevice = result.getDevice();
            //  添加扫描到的蓝牙设备到 set 集合
            boolean addResult = bluetoothDeviceSet.add(bluetoothDevice);
            //  如果 set 集合中未存在该蓝牙对象，则返回true
            if (addResult) {
                log("onScanResult() 发现蓝牙设备" + bluetoothDevice.getName() + "," + bluetoothDevice.getAddress());
                log("目前已经发现" + bluetoothDeviceSet.size() + "个蓝牙设备");

                list.add(new MyBluetoothDevice(false, bluetoothDevice));
                adapter.notifyDataSetChanged();
            }
        }

        @Override
        public void onBatchScanResults(List<ScanResult> results) {
            super.onBatchScanResults(results);
        }

        @Override
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);
        }
    };


    private void initView() {

        handler = new Handler();
        Toolbar toolbar = findViewById(R.id.toolbar);
        TextView tvTitle = findViewById(R.id.tv_title);
        tvTitle.setText("蓝牙连接");
        toolbar.setNavigationIcon(R.mipmap.ic_back_left);
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onBackPressed();
            }
        });
        recycler = findViewById(R.id.recycler);
        recycler.setLayoutManager(new LinearLayoutManager(this));
        recycler.setAdapter(adapter = new DevicesAdapter(R.layout.item_device, list));
        recycler.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));

        adapter.setOnRecyclerViewItemChildClickListener(new BaseQuickAdapter.OnRecyclerViewItemChildClickListener() {

            @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
            @Override
            public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
                pos = position;
                device = (MyBluetoothDevice) adapter.getData().get(position);
                switch (view.getId()) {
                    case R.id.btn_connect:
                        if (!isConnect) {
                            bluetoothGatt = device.getBluetoothDevice().connectGatt(BluetoothActivity2.this, false, bluetoothGattCallback);
                            bluetoothGatt.requestMtu(247);
                        } else {
                            showToast("只支持一个设备连接");
                        }
                        break;
                    case R.id.btn_disconnect:
                        if (bluetoothGatt != null) {
                            bluetoothGatt.disconnect();
                        }
                        break;
                    case R.id.btn_detail:
                        writeBluetoothGattCharacteristic.setValue("aa00aa00".getBytes());
                        bluetoothGatt.writeCharacteristic(writeBluetoothGattCharacteristic);
                        break;
                    case R.id.btn_lvyin:
                        if (writeBluetoothGattCharacteristic == null)
                            return;
                        writeBluetoothGattCharacteristic.setValue("a600a600".getBytes());
                        bluetoothGatt.writeCharacteristic(writeBluetoothGattCharacteristic);
                        isRecord = true;
                        handler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
//                               延迟3秒，同步播放音频
                                new Thread(new RecordPlayingRunnable()).start();
                            }
                        }, 3000);//3
                        break;
                    case R.id.btn_stop:
                        if (writeBluetoothGattCharacteristic == null)
                            return;
                        writeBluetoothGattCharacteristic.setValue("ad00ad00".getBytes());
                        bluetoothGatt.writeCharacteristic(writeBluetoothGattCharacteristic);
                        isRecord = false;
                        break;
                }
            }
        });
    }

    private void initServiceAndChara() {

        List<BluetoothGattService> bluetoothGattServices = bluetoothGatt.getServices();

        for (BluetoothGattService bluetoothGattService : bluetoothGattServices) {
            List<BluetoothGattCharacteristic> characteristics = bluetoothGattService.getCharacteristics();
            for (BluetoothGattCharacteristic characteristic : characteristics) {
                int charaProp = characteristic.getProperties();
                if ((charaProp & BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
                    read_UUID_chara = characteristic.getUuid();
                    read_UUID_service = bluetoothGattService.getUuid();
                    log("read_chara=" + read_UUID_chara + "----read_service=" + read_UUID_service);
                }
                if ((charaProp & BluetoothGattCharacteristic.PROPERTY_INDICATE) > 0) {
                    indicate_UUID_chara = characteristic.getUuid();
                    indicate_UUID_service = bluetoothGattService.getUuid();
                    log("indicate_chara=" + indicate_UUID_chara + "----indicate_service=" + indicate_UUID_service);
                }
                if ((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
                    write_UUID_chara = characteristic.getUuid();
                    write_UUID_service = bluetoothGattService.getUuid();
                    log("write_chara=" + write_UUID_chara + "----write_service=" + write_UUID_service);
                }
                if ((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0) {
                    write_UUID_chara = characteristic.getUuid();
                    write_UUID_service = bluetoothGattService.getUuid();
                    log("write_chara=" + write_UUID_chara + "----write_service=" + write_UUID_service);
                    //  写入服务
                    BluetoothGattService service = bluetoothGatt.getService(write_UUID_service);
                    writeBluetoothGattCharacteristic = service.getCharacteristic(write_UUID_chara);

                    //  发送指令
//                    sendBleData("*".getBytes());
                }
                if ((charaProp & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
                    notify_UUID_chara = characteristic.getUuid();
                    notify_UUID_service = bluetoothGattService.getUuid();
                    log("notify_chara=" + notify_UUID_chara + "----notify_service=" + notify_UUID_service);

                    //  初始化通知服务
                    BluetoothGattService service = bluetoothGatt.getService(notify_UUID_service);
                    notificationBluetoothGattCharacteristic = service.getCharacteristic(notify_UUID_chara);

                    //  开启通知
                    bluetoothGatt.setCharacteristicNotification(notificationBluetoothGattCharacteristic, true);

                    for (BluetoothGattDescriptor dp : characteristic.getDescriptors()) {
                        dp.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                        bluetoothGatt.writeDescriptor(dp);
                    }

                }
            }
        }
    }


    BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);

            //连接状态改变回调
            if (BluetoothGatt.STATE_CONNECTED == newState) {      //  蓝牙连接状态改变 为 -- 已连接
                // 将会回调 本类中的 onServicesDiscovered() 这个方法
                boolean result = gatt.discoverServices();
                if (result) {
                    BluetoothActivity2.this.runOnUiThread(new Runnable() {
                        public void run() {
                            adapter.getData().get(pos).setConnect(true);
                            adapter.notifyItemChanged(pos);
                        }
                    });
                    isConnect = true;
                    //连接完成 停止扫描
                    bluetoothAdapter.cancelDiscovery();
                    showToast("蓝牙连接成功");
                    log("蓝牙连接成功");
                } else {
                    BluetoothActivity2.this.runOnUiThread(new Runnable() {
                        public void run() {
                            adapter.getData().get(pos).setConnect(false);
                            adapter.notifyItemChanged(pos);
                        }
                    });
                    isConnect = false;
                    log("蓝牙连接失败");
                }

            } else if (BluetoothGatt.STATE_DISCONNECTED == newState) {     //  蓝牙连接状态改变为 -- 连接断开
                BluetoothActivity2.this.runOnUiThread(new Runnable() {
                    public void run() {
                        adapter.getData().get(pos).setConnect(false);
                        adapter.notifyItemChanged(pos);
                    }
                });
                isConnect = false;
                log("断开连接");
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            //发现服务回调
            if (status == BluetoothGatt.GATT_SUCCESS) {
                log("发现服务：status=" + status);
                initServiceAndChara();
            }
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicWrite(gatt, characteristic, status);
            //写数据成功
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            //远程特征通知回调

            //  这里将蓝牙传过来的数据转换为 16 进制格式的字符串
            byte[] data = characteristic.getValue();
            byte[] bytes = null;
            if (data.length > 5) {
                bytes = Arrays.copyOfRange(data, 6, data.length - 2);
                //add()和remove()方法在失败的时候会抛出异常(不推荐)
                bufferQueue.offer(bytes);
            }
            if (bytes != null) {
                StringBuilder stringBuilder = new StringBuilder();
                for (byte b : bytes) {
                    stringBuilder.append(String.format("%02x", b));
                }
                log("蓝牙传回来的内容 ( 16进制 ) ： " + stringBuilder.toString());
            }

            log("蓝牙传回来的内容 ( 16进制 原数据) ： " + HexUtil.encodeHexStr(data));

        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorWrite(gatt, descriptor, status);
            //写特征值成功回调
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
            //读取特征值结果回调
        }

        @Override
        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorRead(gatt, descriptor, status);
            //读取描述符结果回调
        }

        @Override
        public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
            super.onReliableWriteCompleted(gatt, status);
            //可靠的写事务完成回调
        }

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
            super.onReadRemoteRssi(gatt, rssi, status);
            //设备信号强度回调
        }

        @Override
        public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
            super.onMtuChanged(gatt, mtu, status);
            //MTU改变回调
        }
    };

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.img_setting:
                break;
        }
    }




    // 采样率
    private int frequency = 8000;
    // 采样通道
    private int channelInConfig = AudioFormat.CHANNEL_IN_MONO;
    // 播放通道 单声道
    private int channelOutConfig = AudioFormat.CHANNEL_OUT_MONO;
    // 16位音频编码
    private int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
    // 录音缓存区
//    private byte[] bufferIn = null;

    // 存放录音缓存的队列
    private Queue<byte[]> bufferQueue = null;

    private class RecordPlayingRunnable implements Runnable {

        @Override
        public void run() {
            tracker.play();
            while (true) {
                byte[] bufferOut = bufferQueue.poll();
                if (bufferOut != null) {
//                    tracker.write(bytes, 0, bytes.length);
                    tracker.write(bufferOut, 0, bufferOut.length);
                }
                if (!isRecord) { //停止录音 弹出循环
                    return;
                }
            }
        }
    }

    /**
     * 日志
     *
     * @param log 日志内容
     */
    private void log(String log) {
        Log.i("蓝牙", log);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_ENABLE) {
            if (resultCode == RESULT_OK) {
                log("用户允许了开启蓝牙的请求");
                log("开始扫描蓝牙设备");
                bluetoothAdapter.getBluetoothLeScanner().startScan(scanCallback);
            } else if (resultCode == RESULT_CANCELED) {
                log("用户拒绝了开启蓝牙的请求");
            }
        }
    }


}
